#ifndef PID_H
#define PID_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

typedef struct
{
  float kp;
  float ki;
  float kd;

  float integral;
  float prev_error;

  float out_min;
  float out_max;

  float integrator_min;
  float integrator_max;

  // Optional smoothing and rate limit
  float meas_filtered;              // internal state for measurement low-pass
  float meas_tau;                   // measurement LPF time constant (s); 0 disables

  float last_output;                // internal state for output smoothing/slew
  float out_tau;                    // output LPF time constant (s); 0 disables
  float max_slew_per_sec;           // max output change per second; 0 disables

  uint8_t meas_filter_initialized;  // lazy init flag
  uint8_t output_initialized;       // lazy init flag
} PIDController;

void PID_Init(PIDController* pid,
              float kp,
              float ki,
              float kd,
              float out_min,
              float out_max,
              float integrator_min,
              float integrator_max);

void PID_Reset(PIDController* pid);

float PID_Compute(PIDController* pid,
                  float setpoint,
                  float measurement,
                  float dt_seconds);

// Configure optional smoothing; pass 0 to disable each
void PID_ConfigFilter(PIDController* pid,
                      float meas_tau_seconds,
                      float out_tau_seconds);

// Configure max output slew rate (units per second); pass 0 to disable
void PID_ConfigSlew(PIDController* pid, float max_rate_per_sec);

#ifdef __cplusplus
}
#endif

#endif // PID_H

